home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
IRIX Installation Tools & Overlays 2001 November
/
SGI IRIX Installation Tools & Overlays 2001 November - Disc 1.iso
/
dist
/
roboinst.idb
/
usr
/
etc
/
roboinst_config.z
/
roboinst_config
Wrap
Text File
|
2001-10-10
|
14KB
|
578 lines
#! /usr/sbin/perl
#Tag 0x00000f00
#ident "$Revision $"
# Copyright 1997-1998, Silicon Graphics, Inc.
# All Rights Reserved.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
# the contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of Silicon Graphics, Inc.
#
# RESTRICTED RIGHTS LEGEND:
# Use, duplication or disclosure by the Government is subject to restrictions
# as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
# and Computer Software clause at DFARS 252.227-7013, and/or in similar or
# successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
# rights reserved under the Copyright Laws of the United States.
# roboinst_config
#
# verifies the format of the roboinst scripts and builds
# a table of contents (list of scripts).
# verifies the format of the mrconfig file.
# Initialization
$TMPDIR = $ENV{'TMPDIR'} || '/usr/tmp';
$ROOT = $ENV{'ROOT'};
@dirs = split(/\//,$0);
$O = "$dirs[$#dirs]";
$Tempfile = "$TMPDIR/${O}.$$";
$RoboDir = "./";
$VERSION = "1";
$GETHOSTBYNAME = "/usr/etc/gethostbyname";
$CFFilename = "mrconfig";
# mrconfig keywords
@cffilenames = (
"init", "fx", "mkfs", "preinst", "postinst"
);
@cfkeywords = (
"version", "partition", "inst", "loghost", "disksetup", "onerror",
"nokernel", "if", "else", "elsif", "endif", "fi", "setenv",
@cffilenames
);
# partition type keywords
@typekeywords = (
"root", "option", "standard",
"xfs", "xfs/blocksize", "efs", "swap",
"preserve", "protect"
);
# size keywords
@sizekeywords = (
"existing", "standard", "all", "remainder"
);
#
# Parse Command Line Options
#
$usage =
"usage: ${O} [ -nx ] [ -c configdir ] \n";
require 'getopts.pl'; # fancy option parsing
if (! &Getopts('c:dnxy')) {
die $usage;
}
if ($opt_c) {
$RoboDir = $opt_c;
$RoboDir .= "/" if ($RoboDir !~ m|/$|);
}
if (! -d $RoboDir) {
die "${RoboDir}: not a directory\n";
}
print "${O}: indexing $RoboDir\n";
chdir($RoboDir) || die "${O}: unable to chdir to $RoboDir\n";
&mrcf_parse($CFFilename);
$IndexFile = ".index";
# miniroot libraries
@mr_solist =
(
"libc.so", "libC.so", "libCsup.so", "libc.so",
"libcrypt.so", "libcurses.so", "libdisk.so", "libgen.so",
"libinst.so", "libm.so", "libmalloc.so", "libw.so"
);
# check directory
&build_index();
exit(0);
#
# ---- end of main processing ----
#
# build_index - check the specified directory for /robo files
sub build_index {
&open_index();
open(FILES,"find . -follow -print |") ||
die "${O}: cannot find files\n";
while (<FILES>) {
chop; # strip eol
s|^\./||; # strip ./
next if (m/^\.index$/ || m/^\.\.?$/);
if (m/\.BAK$/i || m/~$/) { # skip backup files
print "${O}: skipping backup file $_\n";
next;
}
local($name) = $RoboDir . $_;
local($fname) = $_;
print "Checking $fname\n" if ($opt_d);
local($dev,$ino,$modeint,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($fname);
local($mode) = sprintf("%o",$modeint & 0777);
local($ftype) = `file $fname`;
if (-d $fname) {
print INDEX "$fname type=d mode=$mode\n";
} else {
local($executable) = 1;
local($sum) = `sum -r $fname | nawk '{print \$1}'`;
chop($sum);
if ($ftype =~ m|(/bin/[ck]?sh)|) {
local($res) = `$1 -n $fname 2>&1`;
local(@lines) = split(/\n/,$res);
foreach $res (@lines) {
warn "${name}: $res\n";
}
} elsif ($ftype =~ m/:\s+(.*) script text/) {
local($intrp) = $1;
unless ($intrp =~ m,(root|custom)/.*perl,i) {
warn "${name}: ${intrp} script might not run in the miniroot\n";
}
} elsif ($ftype =~ m/:\s+(.*) executable/) {
local($exe) = $1;
if ($ftype !~ m/ELF N(ew )?32/) {
warn "${name}: $exe executable will not run in the miniroot,\n must be ELF New 32 (N32) binary\n";
} else {
if ($ftype =~ m/not stripped/) {
warn "${name}: $exe executable is not stripped, see strip(1)\n";
}
unless (-e "$ROOT/usr/bin/elfdump") {
warn "${O}: unable to check library compatibility, elfdump(1) not installed\n";
} elsif (open(ELF,"elfdump -Dl $fname |")) {
while ($line = <ELF>) {
if ($line =~ m/\s(lib\S+\.so)\S+\s/) {
local($lib) = $1;
local($found) = 0;
foreach (@mr_solist) {
$found = 1 if ($lib eq $_);
}
unless ($found) {
warn "${name}: requires non-miniroot library \"$lib\"\n";
}
}
}
close(ELF);
}
}
} else {
$executable = 0;
}
if ($executable && ! -x _) {
warn "${name}: script should have execute permission\n";
}
if ($fname =~ m/$CFFilename\..*$/) {
warn "${name}: file may be overwritten by roboinst during install,\n it is suggested that you rename the file\n";
}
if ($opt_x) {
print INDEX "$fname type=f mode=$mode\n";
} else {
print INDEX "$fname type=f mode=$mode size=$size sum=$sum\n";
}
}
}
close(FILES);
&close_index();
}
# open_index - open a new index file, prompt if overwrite
sub open_index {
if (! $opt_n) {
if ((! $opt_y) && open(INDEX,"<$IndexFile")) {
close(INDEX);
if (-t) {
print "${O}: index file \"$IndexFile\" exists. Overwrite? [yn] ";
$_ = <STDIN>;
} else {
$_ = "n";
}
if (! m/^\s*[yY]/) {
die "${O}: index file \"$IndexFile\" already exists.\n";
}
}
unlink $IndexFile;
open(INDEX,">$IndexFile") ||
die "$RoboDir${IndexFile}: cannot create\n";
} else {
open(INDEX,"| cat") ||
die "${O}: cannot echo commands\n";
}
print INDEX "# mrscript index\n";
print INDEX "# created by ${O}\n";
print INDEX "# version $VERSION\n";
print "Creating index file \"$RoboDir$IndexFile\"\n" if ($opt_d);
}
sub close_index {
close(INDEX);
}
# mrcf_parse
#
# read and parse the given mrconfig file
# display any errors
sub mrcf_parse {
local($cfname) = @_;
unless (open(MRCF,"<$cfname")) {
print STDERR "${cfname}: unable to open mrconfig file\n";
return;
}
print "Checking $cfname\n" if ($opt_d);
undef %DiskSize;
undef %mrtemp;
undef %mrscripts;
foreach $i (@cffilenames) {
$mrtemp{$i} = "${Tempfile}.$i";
local($fileid) = $i;
$fileid =~ tr/a-z/A-Z/;
eval "open($fileid,\">$mrtemp{$i}\");";
die "${O}: cannot open temporary file \"$mrtemp{$i}\"\n" if $@;
eval "print $fileid \"#! /bin/sh\n\";";
}
while (<MRCF>) {
chop; # strip newline
next unless ($_); # skip blank lines
s/^\s*//; # strip leading whitespace
next if (m/^\#/); # skip comments
local($found) = 0;
foreach $i (@cfkeywords) {
if (m/^$i>?\s*$/i || m/^$i>?\s?(.*)$/i) {
# strip extra whitespace
local($args) = $1;
$args =~ s/(\W)/\\$1/g;
eval "&cfkey_$i(\"$args\")";
$found = 1;
last;
}
}
unless ($found) {
warn "${cfname}: unknown directive \"$_\"\n";
}
}
close(MRCF);
foreach $i (@cffilenames) {
local($fileid) = $i;
$fileid =~ tr/a-z/A-Z/;
eval "close($fileid);";
die "${O}: cannot close temporary file \"$mrtemp{$i}\"\n" if $@;
print "Checking $i script $mrtemp{$i}\n" if $opt_d;
local($res) = `/bin/sh -n $mrtemp{$i} 2>&1`;
$res =~ s/^${Tempfile}\.//;
warn "mrconfig: $res" if ($res);
unlink $mrtemp{$i};
}
}
sub cfkey_partition {
local($argstr) = @_;
local($disk);
local($partition,$size,$type,$name,$options) = split(' ',$argstr,5);
# verify partition
if ($partition =~ m/(\S+):(\/\S+)/) { # network disk
local($server,$path) = ($1,$2);
`/usr/etc/ping -q -c 1 $server`;
unless ($?) {
warn "${server}: unable to contact remote host\n";
}
if ($path !~ m|^(/\w*)+$|) {
warn "${partition}: partition has questionable pathname\n";
}
unless ($type eq "nfs") {
warn "${partition}: remote disk must have type \"nfs\"\n";
}
$disk = $type; # shouldn't be used, but better to have a value
} else {
unless ($partition =~ m/^(dks[0-9]+d[0-9]+)(vh|vol|s[0-9]+)$/ ||
$partition =~ m/^(systemdisk[0-9]*)(vh|vol|s[0-9]+|)$/) {
$disk = $1;
warn "${partition}: partition does not seem to specify a legal disk\n";
}
if ($type eq "nfs") {
warn "${partition}: local disk cannot have type \"nfs\"\n";
}
}
# verify size
$size =~ tr/A-Z/a-z/; # lowercase
local($sz_start,$sz_block) = ("0","0");
if ($size =~ m/:/) {
($sz_start,$size) = split(':',$size,2);
}
if ($size =~ m|/|) {
($size,$sz_block) = split('/',$size);
}
if ($sz_start =~ m/^followspart([0-9]+)/) {
# processing unknown
} elsif ($sz_start !~ m/^[0-9]+$/) {
warn "${partition}: partition start address \"$sz_start\" is invalid\n";
}
unless ($sz_block =~ m/^[0-9]+$/ && # numeric
($sz_block % 512 == 0) && # multiple of 512
($sz_block <= 65536)) { # maximum size
warn "${partition}: partition blocksize \"$sz_block\" is invalid\n";
}
if ($size =~ m/^([0-9]+)(%?)$/) {
if ($2) { # percentage
# NOTE: currently not supported...
local($total) = $DiskSize{$disk} + $1;
if ($total > 100) {
warn "${partition}: partition percentage totals more than 100%\n";
}
$DiskSize{$disk} = $total;
}
} else {
# there is no way to do a more detailed check without parsing
# the "if" statements in mrconfig, as well as knowing the size
# of the target disk(s).
unless (grep(/^$size$/, @sizekeywords)) {
warn "${partition}: partition size \"$size\" is invalid\n";
}
}
# check type
if ($type =~ m|/|) {
($type,$xfs_block) = split('/',$type);
} else {
$xfs_block = "4096";
}
local($found) = 0;
foreach $i (@typekeywords) {
if ($type eq $i) {
$found = 1;
last;
}
}
if ($found) {
if ($type eq "swap") {
if ($name ne "swap" && $name ne "") {
warn "${partition}: swap partition does not have name \"swap\"\n";
}
} elsif ($type eq "xfs") {
unless ($xfs_block =~ m/^[0-9]+$/ && # numeric
($xfs_block % 512 == 0) && # multiple of 512
($xfs_block <= 65536)) { # maximum size
warn "${partition}: partition blocksize \"$xfs_block\" is invalid\n";
}
} elsif ($type eq "protect") {
# do nothing
} elsif ($type eq "root" || $type eq "option" || $type eq "miniroot") {
warn "${partition}: $type partition must specify size \"standard\"\n"
unless ($size eq "standard");
} else { # not swap
if ($name eq "nomount") {
print "${partition}: nomount\n" if ($opt_d);
} elsif ($name !~ m|^(/\w*)+$|) {
warn "${partition}: partition has questionable mount point \"$name\"\n";
}
}
} else {
warn "${partition}: partition has invalid type \"$type\"\n";
}
}
sub cfkey_version {
local($version) = @_;
if (int($version) > int($VERSION)) {
warn "${cfname}: version $version not supported (newer than $VERSION)\n";
}
}
sub cfkey_onerror {
local($action) = @_;
if ($action ne "wait" && $action ne "ignore" && $action ne "abort") {
warn "${cfname}: onerror keyword requires one of the following arguments: wait, ignore, abort\n";
}
}
sub cfkey_nokernel {
local($typestr) = @_;
warn "${cfname}: nokernel takes no options ($typestr)\n" if ($typestr);
}
sub cfkey_disksetup { # if it's here, it's
local($typestr) = @_;
warn "${cfname}: disksetup takes no options ($typestr)\n" if ($typestr);
}
sub cfkey_setenv {
local ($var, $val) = @_;
if ($var eq "") {
warn "${cfname}: setenv keyword takes a variable name\n";
}
}
sub cfkey_loghost {
local($server) = @_;
print "Checking loghost $server\n" if ($opt_d);
local($host);
chop($host = `hostname`);
local($thisipaddr) = &getipaddr($host);
foreach $host (split(' ',$server)) {
local($ipaddr);
if ($host !~ m/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) {
warn "${cfname}: loghost \"$host\" should be specified as IP address\n";
}
if ($host eq "localhost") {
$ipaddr = $thisipaddr;
} else {
$ipaddr = &getipaddr($host);
}
print " loghost $host ($ipaddr)\n" if ($opt_d);
if ($ipaddr eq "0") {
warn "${cfname}: unknown loghost $host\n";
}
}
}
# no verification performed on inst commands
sub cfkey_inst {
local($cmd) = @_;
print "${cfname}: inst $cmd\n" if ($opt_d);
}
sub script_check {
local($script,$cmd) = @_;
if (! defined $mrscripts{$script}) {
if (-e "mr$script") {
warn "${cfname}: $script command overrides mr$script, mr$script script will not be run\n";
}
$mrscripts{$script} = 1;
}
}
sub cfkey_fx {
local($cmd) = @_;
local($script) = "fx";
&script_check($script,$cmd);
print FX $cmd,"\n"; # I don't like this, but it works
}
sub cfkey_init {
local($cmd) = @_;
local($script) = "init";
&script_check($script,$cmd);
print INIT $cmd,"\n";
}
sub cfkey_mkfs {
local($cmd) = @_;
local($script) = "mkfs";
&script_check($script,$cmd);
print MKFS $cmd,"\n";
}
sub cfkey_preinst {
local($cmd) = @_;
local($script) = "preinst";
&script_check($script,$cmd);
print PREINST $cmd,"\n";
}
sub cfkey_postinst {
local($cmd) = @_;
local($script) = "postinst";
&script_check($script,$cmd);
print POSTINST $cmd,"\n";
}
# getipaddr - get the IP address for a given host ($1)
# returns the IP address in IPADDR global variable
# returns 1 if got a name
sub getipaddr {
local($hostname) = @_;
if (! -x $GETHOSTBYNAME) {
print "${O}: $GETHOSTBYNAME not installed, unable to lookup hostname\n";
return "0";
}
local($addr) = `$GETHOSTBYNAME $hostname | \
nawk -v a=0 '/^$hostname / { a=\$3; exit }
END { print a }'`;
chop $addr;
return $addr;
}